package com.JustTest;

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

/**
 * JustTest
 */

/**
 * 使用final是所谓的安全发布（safe publication）的一种方式，这里，发布（publication）一个地相意味着在一个线程中创建它，同时另一个线程在之后的某时刻可以引用到该新创建的对象。
 * 当JVM调用对象的构造函数时，它必须将各成员赋值，同时存储一个指向该对象的指针。就像其他任何的数据写入一样，
 * 这可能是乱序的，and their application to main memory can be delayed and other processors can be delayed unless you take special steps to combat this
 * （看不太懂，是不是说“把他们写回主存可能推迟，并且其他的处理器（看到变化）也会推迟，要客服这一点，除非采取非常步骤”）。
 * 特别的，指向对象的引用可能在成员变量提交之前（导致如此的原因之一是编译器的指令重排ordering：if you think about how you'd write things in a low-level language such as C or assembler,
 * it's quite natural to store a pointer to a block of memory, and then advance the pointer as you're writing data to that block）就被写入到主存并被访问到了。这样会导致另一个线程看到了一个不合法或不完整的对象。
 * 而final可以防止此类事情的发生：如果某个成员是final的，JVM规范做出如下明确的保证：一旦对象引用对其他线程可见，则其final成员也必须正确的赋值了。
 */
public class App {

    private static boolean bChanged;
    private int port = 8189;// 默认服务器端口

    public App() {
    }

    // 创建指定端口的服务器
    public App(int port) {
        this.port = port;
    }

    // 回溯算法实现。注意：我把输入的变量都定义成了成员变量。
    private static int maxW = Integer.MIN_VALUE; // 结果放到 maxW 中
    private static int[] weight = {2,2,4,6,3};  // 物品重量
    private static int n = 5; // 物品个数
    private static int w = 9; // 背包承受的最大重量

    public static void main(String[] args) throws Exception {
//        new App().service();
//        new App().runThread();
//        SynchronousQueueTest();
//        ReentrantLock lock = new ReentrantLock();
//        new Thread(new myLockRunnable(1, lock)).start();
//        new Thread(new myLockRunnable(2, lock)).start();
//        ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
//        new Thread(new myReadWriteLockRunnable(1, lock.readLock(), 30000)).start();
//        Thread.sleep(3000);
//        new Thread(new myReadWriteLockRunnable(2, lock.readLock(), 30)).start();

//          Source source = new Source();
//          ListEventRunnable listEventRunnable =  new ListEventRunnable(source);
//          new Thread(listEventRunnable).start();
//          Thread.sleep(3000);
//          ThisEscape thisEscape = new ThisEscape(source);
//         Holder holder = new Holder(1);
//         new Thread(new myRunable3(holder)).start();
//        while(true){
//            holder = new Holder(new Random().nextInt());
//        }
//        FinalTest finalTest = null;
//        new Thread(new finalRunnable(finalTest, 10000, 1, 2)).start();
//        Thread.sleep(3000);
//        new Thread(new finalRunnable(finalTest, 1, 3, 4)).start();
//        Thread.sleep(13000);
//        System.out.println(finalTest);


//        Integer[] a = new Integer[3];
//        a[0] = 1;
//        a[1] = 2;
//        a[2] = 3;
//        CopyOnWriteArrayList copyOnWriteList = new CopyOnWriteArrayList(a);
//
//        new Thread(new CopyOnWriteRunnable(copyOnWriteList)).start();
//        new Thread(new CopyOnWriteRunnable2(copyOnWriteList)).start();

//        TaskProcesser<Task,String> taskTaskProcesser = new TaskProcesser<Task, String>() {
//            @Override
//            public String doProcess(Task task) {
//                try {
//                    Thread.sleep(3000);
//                    System.out.println(task.getName()+":"+task.getId());
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//                return task.getName()+":"+task.getId();
//            }
//        };
//
//        WorkThread<Task,String> workThread = new WorkThread<Task, String>(taskTaskProcesser,new ArrayBlockingQueue<Runnable>(3));
//
//
//
//        new Thread(workThread).start();
//
//
//        Future<String> result = workThread.submit(new Task(1,"mike"));
//
//        System.out.println("wait.........");
////        workThread.submit(new Task(2,"will"));
//        Thread.sleep(4000);
//
//        System.out.println(result.get());


//
//        new Thread() {
//
//            @Override
//            public void run() {
//                for (;;) {
//                    if (bChanged == !bChanged) {
//                        System.out.println("!=");
//                        System.exit(0);
//                    }
//                }
//            }
//        }.start();
//        Thread.sleep(1);
//        new Thread() {
//
//            @Override
//            public void run() {
//                for (;;) {
//                    bChanged = !bChanged;
//                }
//            }
//        }.start();


//        Watcher wh = new Watcher() {
//
//            @Override
//            public void process(WatchedEvent event) {
//
//                System.out.println("回调watcher实例： 路径" + event.getPath() + " 类型："
//
//                        + event.getType());
//
//            }
//
//        };
//
//
//        ZooKeeper zk = new ZooKeeper("127.0.0.1:21811", 500000, wh);
//
//        System.out.println("---------------------");
//
//// 创建一个节点root，数据是mydata,不进行ACL权限控制，节点为永久性的(即客户端shutdown了也不会消失)
//
//        zk.exists("/root", true);
//
//        zk.create("/root", "mydata".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,
//
//                CreateMode.PERSISTENT);
//
//        System.out.println("---------------------");
//
//// 在root下面创建一个childone znode,数据为childone,不进行ACL权限控制，节点为永久性的
//
//        zk.exists("/root/childone", true);
//
//        zk.create("/root/childone", "childone".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,
//
//                CreateMode.PERSISTENT);
//
//        System.out.println("---------------------");
//
//// 删除/root/childone这个节点，第二个参数为版本，－1的话直接删除，无视版本
//
//        zk.exists("/root/childone", true);
//
//        zk.delete("/root/childone", -1);
//
//        System.out.println("---------------------");
//
//        zk.exists("/root", true);
//
//        zk.delete("/root", -1);
//
//        System.out.println("---------------------");
//
//// 关闭session
//
//        zk.close();

//        HashMap<String,Object> param = new HashMap<>();
//        param.put("userId",12345);
//        param.put("userType",12345);
//        sendPost("http://localhost:8080/upload/authorize",param,"utf-8");

//        new Thread(new Runnable() {
//            @Override
//            public void run() {
//                DistributeLock d1 = new DistributeLock("localhost:2181", "test1");
//                d1.lock();
//                try {
//                    TimeUnit.SECONDS.sleep(6);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//                d1.unlock();
//            }
//        }).start();
//        new Thread(new Runnable() {
//            @Override
//            public void run() {
//                DistributeLock d1 = new DistributeLock("localhost:2181", "test1");
//                d1.lock();
//                try {
//                    TimeUnit.SECONDS.sleep(6);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//                d1.unlock();
//            }
//        }).start();
//        new Thread(new Runnable() {
//            @Override
//            public void run() {
//                DistributeLock d1 = new DistributeLock("localhost:2181", "test1");
//                d1.lock();
//                try {
//                    TimeUnit.SECONDS.sleep(6);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//                d1.unlock();
//            }
//        }).start();
//        new Thread(new Runnable() {
//            @Override
//            public void run() {
//                DistributeLock d1 = new DistributeLock("localhost:2181", "test3");
//                d1.lock();
//                try {
//                    TimeUnit.SECONDS.sleep(6);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//                d1.unlock();
//            }
//        }).start();
//
//
//        new Thread(new Runnable() {
//            @Override
//            public void run() {
//                DistributeLock d1 = new DistributeLock("localhost:2181", "test3");
//                d1.lock();
//                try {
//                    TimeUnit.SECONDS.sleep(6);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//                d1.unlock();
//            }
//        }).start();
//
//        new Thread(new Runnable() {
//            @Override
//            public void run() {
//                DistributeLock d1 = new DistributeLock("localhost:2181", "test1");
//                d1.lock();
//                try {
//                    TimeUnit.SECONDS.sleep(6);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//                d1.unlock();
//            }
//        }).start();

//        String test = "test";
//        byte[] bytes = test.getBytes();
//        System.out.println("args = [" + args + "]");





//       f(0,0);
        Integer i = 3;
//        boolean b = (Boolean)i;


    }

    public static void f(int i, int cw) { // 调用 f(0, 0)
        System.out.println("i = [" + i + "], cw = [" + cw + "]\n");
        if (cw == w || i == n) { // cw==w 表示装满了，i==n 表示物品都考察完了
            if (cw > maxW) maxW = cw;
            return;
        }
        f(i+1, cw); // 选择不装第 i 个物品
        if (cw + weight[i] <= w) {
            f(i+1,cw + weight[i]); // 选择装第 i 个物品
        }
    }


    public static String sendPost(String urlParam, Map<String, Object> params, String charset) {
        StringBuffer resultBuffer = null;
        // 构建请求参数
        StringBuffer sbParams = new StringBuffer();
        if (params != null && params.size() > 0) {
            for (Map.Entry<String, Object> e : params.entrySet()) {
                sbParams.append(e.getKey());
                sbParams.append("=");
                sbParams.append(e.getValue());
                sbParams.append("&");
            }
        }
        HttpURLConnection con = null;
        OutputStreamWriter osw = null;
        BufferedReader br = null;
        // 发送请求
        try {
            URL url = new URL(urlParam);
            con = (HttpURLConnection) url.openConnection();
            con.setRequestMethod("POST");
            con.setDoOutput(true);
            con.setDoInput(true);
            con.setUseCaches(false);
            con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            con.setRequestProperty("Access-Control-Allow-Origin", "*");
            if (sbParams != null && sbParams.length() > 0) {
                osw = new OutputStreamWriter(con.getOutputStream(), charset);
                osw.write(sbParams.substring(0, sbParams.length() - 1));
                osw.flush();
            }
            // 读取返回内容
            resultBuffer = new StringBuffer();
            int contentLength = Integer.parseInt(con.getHeaderField("Content-Length"));
            if (contentLength > 0) {
                br = new BufferedReader(new InputStreamReader(con.getInputStream(), charset));
                String temp;
                while ((temp = br.readLine()) != null) {
                    resultBuffer.append(temp);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (osw != null) {
                try {
                    osw.close();
                } catch (IOException e) {
                    osw = null;
                    throw new RuntimeException(e);
                } finally {
                    if (con != null) {
                        con.disconnect();
                        con = null;
                    }
                }
            }
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    br = null;
                    throw new RuntimeException(e);
                } finally {
                    if (con != null) {
                        con.disconnect();
                        con = null;
                    }
                }
            }
        }

        return resultBuffer.toString();
    }


    private static void RegisterWatcher(final ZooKeeper zooKeeper) {
        zooKeeper.register(new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                System.out.println("test callback");
                RegisterWatcher(zooKeeper);
            }
        });
    }


    private static void SynchronousQueueTest() throws InterruptedException {
        final SynchronousQueue queue = new SynchronousQueue();
        new Thread(new Runnable() {
            public void run() {
                while (true) {
                    try {
                        System.out.println(queue.take());
                        break;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        Thread.sleep(3000);
        System.out.println(queue.offer(1));
    }

    public void runThread() {
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        break;
                    }
                    System.out.println("123");
                }
            }
        });
        t1.start();
        try {
            Thread.sleep(9000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t1.interrupt();
        System.out.println(t1.isInterrupted());
    }

    // 提供服务
    public void service() {
        byte[] b = new byte[1024];
        try {// 建立服务器连接
            ServerSocket server = new ServerSocket(port);
            // 等待客户连接
            Socket socket = server.accept();
            try {
                // 读取客户端传过来信息的DataInputStream
                BufferedInputStream in = new BufferedInputStream(socket
                        .getInputStream());
                while (true) {
                    // 读取来自客户端的信息
                    in.read(b);
                    System.out.println(new String(b));
//                    String send = scanner.nextLine();
//                    System.out.println("服务器：" + send);
//                    // 把服务器端的输入发给客户端
//                    out.writeUTF("服务器：" + send);
                }
            } finally {// 建立连接失败的话不会执行socket.close();
                socket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static class TestRunnable implements Runnable {
        Test a;

        public TestRunnable(Test a) {
            this.a = a;
        }

        @Override
        public void run() {
            for (; ; ) {
//                a.a = String.valueOf(new Random().nextInt(22));
            }
        }
    }

    static class CopyOnWriteRunnable implements Runnable {
        CopyOnWriteArrayList copyOnWriteList;

        public CopyOnWriteRunnable(CopyOnWriteArrayList copyOnWriteList) {
            this.copyOnWriteList = copyOnWriteList;
        }

        public void run() {
            while (true) {
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + ":" + this.copyOnWriteList.get(2));
            }
        }
    }

    static class CopyOnWriteRunnable2 implements Runnable {
        CopyOnWriteArrayList copyOnWriteList;

        public CopyOnWriteRunnable2(CopyOnWriteArrayList copyOnWriteList) {
            this.copyOnWriteList = copyOnWriteList;
        }

        @Override
        public void run() {
            copyOnWriteList.set(2, 4);
            while (true) {
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + ":" + this.copyOnWriteList.get(2));
            }
        }
    }

    static class finalRunnable implements Runnable {
        FinalTest finalTest;
        long time;
        int x;
        int y;

        public finalRunnable(FinalTest finalTest, long time, int x, int y) {
            this.finalTest = finalTest;
            this.time = time;
            this.x = x;
            this.y = y;
        }

        public void run() {
            finalTest = new FinalTest(x, y, time);
            System.out.println(finalTest);

        }
    }

    static class myRunable2 implements Runnable {
        Holder holder;

        public myRunable2(Holder holder) {
            this.holder = holder;
        }

        public void run() {
            while (true) {
                holder = new Holder(new Random().nextInt());
            }
        }
    }

    static class myRunable3 implements Runnable {
        Holder holder;

        public myRunable3(Holder holder) {
            this.holder = holder;
        }

        public void run() {
            try {
                while (true) {
                    holder.assertSanity();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    static class Holder {
        int n;

        public Holder(int n) {
            this.n = n;
        }

        public void assertSanity() throws Exception {
            if (n != n) {
                System.out.println(n);
                throw new Exception("n != n");
            } else {
                System.out.println(n);
            }
        }
    }

    static class ThisEscape {
        int i;
        int j;

        public ThisEscape(Source source) {
            this.i = 3;
            source.add(new InnerClass() {
                @Override
                public void doSth() {
                    System.out.println(ThisEscape.this.i);
                    System.out.println(ThisEscape.this.j);
                }
            });
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.j = 4;
        }
    }

    static class ListEventRunnable implements Runnable {
        Source source;

        public ListEventRunnable(Source source) {
            this.source = source;
        }

        public void run() {
            while (true) {
                System.out.println("ListEventRunnable in");
                for (InnerClass innerClass : source.get()) {
                    innerClass.doSth();
                }
                break;
            }
        }
    }

    static class Source {
        List<InnerClass> innerClasses = new ArrayList<InnerClass>();

        public synchronized void add(InnerClass innerClass) {
            innerClasses.add(innerClass);
            this.notifyAll();
        }

        public synchronized List<InnerClass> get() {
            if (innerClasses.size() <= 0) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return innerClasses;
        }


    }

    abstract static class InnerClass {
        public abstract void doSth();
    }

    static class myLockRunnable implements Runnable {
        private int i;
        private Lock lock;

        public myLockRunnable(int i, Lock lock) {
            this.i = i;
            this.lock = lock;
        }

        public void run() {
            Thread.currentThread().setName("myLockRunnable" + i);
            try {
                System.out.println(Thread.currentThread().getName() + "lock in");
                lock.lock();
                Thread.sleep(300000);
                System.out.println(Thread.currentThread().getName() + "lock end");
                lock.unlock();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    static class myReadWriteLockRunnable implements Runnable {
        private int i;
        private Lock lock;
        private long sleepTime;

        public myReadWriteLockRunnable(int i, Lock lock, long sleepTime) {
            this.i = i;
            this.lock = lock;
            this.sleepTime = sleepTime;
        }

        public void run() {
            Thread.currentThread().setName("myLockRunnable" + i);
            try {
                System.out.println(Thread.currentThread().getName() + "lock in");
                lock.lock();
                Thread.sleep(sleepTime);
                System.out.println(Thread.currentThread().getName() + "lock end");
                lock.unlock();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
